﻿// Manages the children of the element. But the children also are named members of the element
define([
    'Wjs/ui/elements/mixins/Container',
    'Wjs/ui/elements/mixins/Loadable'
],
function () {
    'use strict';

    return Wjs.defineOnce({

        type: 'HashContainer',

        internal: {

            base: Wjs.getType('Container'),

            mixins: [
                Wjs.getType('Loadable')
            ],

            construct: function () {

                this.sections = {};
            },

            // No need to initialize, the base type calls the correct addChildren function

            // Listeners are not inherited to avoid undesired side effects
            listeners: {

                onDomElementCreated: function () {
                    var fragment;

                    if (this.sections) { // There are sections

                        fragment = document.createDocumentFragment();

                        // Render the section elements
                        for (var name in this.sections) {

                            this.sections[name].render(fragment); // If fragment provided, then call fragment.appendChild(item);
                        }

                        this.domEl.appendChild(fragment);

                        // Fire the item rendered event
                        if (this.itemsRenderedHandler) {

                            this.itemsRenderedHandler();
                        }
                    }
                },

                // Called before the element is destroyed
                onDestroy: function () {

                    this.clearSections();
                }
            }

        },

        getSections: function () {

            return this.sections;
        },

        getSection: function (name) {

            return this.sections[name];
        },

        // The section is equivalent to item
        addSection: function (name, section) {

            section = this.createItem(section);

            section.setParent(this);

            if (this.sections[name]) {

                throw 'Section with name: ' + name + 'already exists in type: ' + this.type;
            }

            this.sections[name] = section;

            this.handleItemAdded(section);

            return this;
        },

        addSections: function (sections) {

            if (!Wjs.isObject(sections)) {

                throw 'Parameter must be a plain object';
            }

            for (var name in sections) {

                this.addSection(name, sections[name]);
            }
        },

        // Replaces a section with the same name
        replaceSection: function (name, section) {
            var oldSection = this.sections[name];

            oldSection.destroy(); // Destroy the item in the section

            if (this.itemRemovedHandler) {

                this.itemRemovedHandler(oldSection);
            }

            this.sections[name] = null;

            // delete this.sections[name]; // Keep the existing section

            this.addSection(name, section);
        },

        clearSections: function () {

            if (this.sections) {

                for (var name in this.sections) {

                    this.sections[name].destroy();
                }
            }

            this.sections = {}; // Reset the sections

            if (this.itemsClearedHandler) {

                this.itemsClearedHandler();
            }
        },

        // Recursively returns all the items of this view that match the criteria of the test function
        down: function (test, output) {
            var done = false,
                section;

            if (!output) { // Assume parent will not provide the output array

                output = [];
                done = true;
            }

            for (var name in this.sections) {

                section = this.sections[name];

                if (!test || test(section)) {

                    output.push(section);
                }

                if (section.down) { // Recurse

                    section.down(test, output);
                }
            }

            if (done) {

                return output;
            }
        },

        beforeLoadHandler: function () {
            // Do nothing
        },

        loadHandler: function (data, contentType) {

            if (this.sections) { // There are sections

                for (var name in this.sections) {

                    sections[name].loadData(data);
                }
            }
        }
    });

});